package Extends;/*
 *
 * @author 陈粒
 * @version 创建时间：2021/7/8 19:05
 */

/**
 * 继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类，新的类能吸收已有类的数据属性和行为，
 * 并能扩展新的能力。
 * 继承的限制：
 * 限制一：一个子类只能够继承一个父类，存在单继承局限。
 * 限制二：在一个子类继承的时候，实际上会继承父类之中的所有操作（属性、方法），但是需要注意的是，
 * 对于所有的非私有（no private）操作属于显式继承（可以直接利用对象操作），而所有的私有操作属于隐式继承（间接完成）
 * 限制三：在继承关系之中，如果要实例化子类对象，会默认先调用父类构造，为父类之中的属性初始化，之后再调用子类构造，为子类之中的属性初始化。
 * 即：默认情况下，子类会找到父类之中的无参构造方法，也就是子类构造函数默认都有super();
 * 注意：而如果这个时候父类只创建带参构造函数覆盖掉默认构造函数后(父类无参构造函数相当于消失了)，则子类必须通过super()调用指定参数的构造方法，
 * 也就是必须调用父类无参构造函数，程序就会出现编译错误，给父类创建无参构造函数后就编译正确。
 * 一句话：父类不能只创建带参构造函数，要么什么构造函数都不创建，要么只创建无参构造函数，要么无参构造函数和
 * 带参构造函数都创建
 * 继承的初始化：
 * 先初始化父类的成员变量，在初始化子类的成员变量
 * 在任意加载顺序下，先调用父类static代码块，在调用子类static代码块
 */
public class Extends {//测试类

    public static void main(String[] args) {
        //限制二
        B2 b2 = new B2();//创建子类B2的对象b2
        b2.setS("李四");//调用子类B2的父类A2的setter方法，给父类的私有变量s赋值
        System.out.println(b2.getS());//调用子类B2的父类A2的getter方法，返回s的值给主函数用以输出
        System.out.println("------------------");
        new B3();//创建子类B3对象用以调用子类B3无参构造函数
    }
}

//限制一
class A1 {

}

class B1 extends A1 {//单继承，子类B1只能继承一个父类A1

}

//限制二
class A2 {
    private String s;

    public String getS() {
        return s;
    }

    public void setS(String s) {
        this.s = s;
    }
}

class B2 extends A2 {
    void Test2() {
        //System.out.println(s);//直接调用父类私有变量s会出错
    }
}

class A3{
    public A3() {
        System.out.println("父类A3无参构造函数");
    }
}

class B3 extends A3{
    public B3() {
        //默认有super();
        System.out.println("子类B3无参构造函数");
    }
}